/**
 * Description:
 * Class Name:SynchronizedDrawThread
 * Date:2022/5/6 15:20
 *
 * @author LTisme
 * @version JAVA17
 */
package 疯狂Java讲义.第16章_多线程._16_5_同步线程._16_5_2_同步代码块之解决银行取钱问题;

import 疯狂Java讲义.第16章_多线程._16_5_同步线程._16_5_1_线程安全问题之银行取钱问题.Account;

public class SynchronizedDrawThread extends Thread{
    // 模拟用户账户
    private Account account;
    // 当前线程希望的取钱数
    private double drawAmount;
    public SynchronizedDrawThread(String name, Account account, double drawAmount){
        super(name);
        this.account = account;
        this.drawAmount = drawAmount;
    }

    // 当多个线程修改同一个共享数据时，将涉及数据安全问题
    @Override
    public void run() {
        // 使用 account 作为同步监视器，任何线程进入下面的同步代码块之前
        // 必须先获得对 account 账户的锁定
        // 这种做法符合：加锁→修改→释放锁 的逻辑
        synchronized (account){
            // 账户余额大于取钱数目，则可取钱
            if (account.getBalance() >= drawAmount){
                // 吐出钞票
                System.out.println(getName() + "取钱成功！吐出钞票：" + drawAmount + " 元");
                try {
                    Thread.sleep(1);
                }
                catch (InterruptedException e){
                    e.printStackTrace();
                }
                // 修改余额
                account.setBalance(account.getBalance() - drawAmount);
                System.out.println("\t余额为：" + account.getBalance());
            }
            else {
                System.out.println(getName() + " 抱歉，余额不足！");
            }
        }
        // 同步代码块结束，该线程会释放同步锁
    }
}
